package se.webbzon.oschi01.command;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Stack;

public class History implements CommandListener {
	
	private final ArrayList<HistoryListener> listeners;
	private final ArrayDeque<Command> history;
	private final Stack<Command> future;
	private int capacity;
	
	public History() {
		this(20);
	}
	
	public History(int capacity) {
		listeners = new ArrayList<HistoryListener>();
		history = new ArrayDeque<Command>(capacity);
		future = new Stack<Command>();
		this.capacity = capacity;
	}
	
	public boolean canRedo() {
		return !future.isEmpty();
	}
	
	public boolean canUndo() {
		return !history.isEmpty();
	}
	
	public void redo() {
		Command c = future.pop();
		c.redo();
		history.addLast(c);
		notifyHistoryRedo();
	}
	
	public void undo() {
		Command c = history.removeLast();
		c.undo();
		future.push(c);
		notifyHistoryUndo();
		
	}
	
	public boolean addListener(HistoryListener listener) {
		return listeners.add(listener);
	}
	
	public boolean removeListener(HistoryListener listener) {
		return listeners.remove(listener);
	}
	
	@Override public void performCommand(Command command) {
		future.clear();
		if (history.size() >= capacity)
			history.removeFirst();
		history.addLast(command);
		command.redo();
		notifyHistoryRedo();
	}

	/*@Override public void onUndo(Command command) {
		if (history.size() > 0) {
			Command c = history.removeLast();
			if (c == command) {
				future.push(c);
			} else {
				history.addLast(c);
				throw new IllegalStateException("Can not undo unhappened command.");
			}
		} else {
			future.clear();
		}
		notifyHistoryUndo();
	}*/
	
	private void notifyHistoryUndo() {
		for (HistoryListener listener : listeners)
			listener.onHistoryUndo(this);
	}
	
	private void notifyHistoryRedo() {
		for (HistoryListener listener : listeners)
			listener.onHistoryRedo(this);
	}

}
